package com.chenfan.mcn.config;

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.StringCodec;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.clients.privilege.PrivilegeClient;
import com.chenfan.privilege.common.config.SearchAuthorityHandler;
import com.chenfan.privilege.common.config.UrlAuthHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;

/**
 * 公用拦截器 监听数据源切换
 *
 * @author lizhejin
 */
@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final StringRedisTemplate stringRedisTemplate;
    private final BaseInfoClient baseInfoClient;

    @Autowired
    private ObjectFactory<PrivilegeClient> privilegeFactory;

    @Autowired
    public WebMvcConfig (@Lazy StringRedisTemplate stringRedisTemplate, @Lazy BaseInfoClient baseInfoClient) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.baseInfoClient = baseInfoClient;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        PrivilegeClient privilegeClient = Optional.of(privilegeFactory.getObject()).orElseThrow(() -> new RuntimeException("not privilege ben configured"));
        registry.addInterceptor(new UrlAuthHandler(stringRedisTemplate)).addPathPatterns("/**");
        registry.addInterceptor(new AuthenticationHandlerInterceptor(privilegeClient)).addPathPatterns("/**").excludePathPatterns("/swagger-ui/**", "/swagger-resources/**", "/v2/api-docs");
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new SearchAuthorityHandler("chenfan-cloud-mcn", stringRedisTemplate, baseInfoClient));
    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        if(CollectionUtils.isNotEmpty(converters)) {
            converters.forEach(converter -> {

                if(converter instanceof FastJsonHttpMessageConverter) {
                    FastJsonConfig fastJsonConfig = ((FastJsonHttpMessageConverter)converter).getFastJsonConfig();
                    //不设置全局的DateFormate与@JSONField(format=...冲突，fastjson默认日期格式=yyyy-MM-dd HH:mm:ss
                    fastJsonConfig.setDateFormat(null);
                    //接口（反）序列化-字符串字段前后去空格
                    fastJsonConfig.setFeatures(ArrayUtils.add(fastJsonConfig.getFeatures(), Feature.TrimStringFieldValue));
                    //https://github.com/alibaba/fastjson/issues/3279  从1.2.69版本开始，自定义StringCodec会失效
                    StringCodec trimStringCodec = new StringCodec(){
                        @Override
                        public String deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
                            return StringUtils.trim(super.deserialze(parser,clazz,fieldName));
                        }

                        @Override
                        public void write(JSONSerializer serializer, String value) {
                            super.write(serializer, StringUtils.trim(value));
                        }
                    };
                    fastJsonConfig.getParserConfig().putDeserializer(String.class,trimStringCodec);
                    fastJsonConfig.getParserConfig().putDeserializer(StringBuffer.class,trimStringCodec);
                    fastJsonConfig.getParserConfig().putDeserializer(StringBuilder.class,trimStringCodec);
                    //com.chenfan.common.config.FastJsonConverterConfig 重置了
                    fastJsonConfig.getSerializeConfig().put(String.class,trimStringCodec);
                    fastJsonConfig.getSerializeConfig().put(StringBuffer.class,trimStringCodec);
                    fastJsonConfig.getSerializeConfig().put(StringBuilder.class,trimStringCodec);
                }
            });
        }
    }
}
